use axum::{
    middleware::from_fn,
    routing::{get, get_service, post},
    Router,
};
use blog::{
    auth::auth,
    config::AppContext,
    controller::{
        class_controller, login_controller, reply_controller, setting_controller, topic_controller,
        widget_controller,
    },
    job::init_cron,
    service::topic_service,
    template, DATA_ROOT, STATIC_PATH, STATIC_PREFIX,
};
use dirs::home_dir;

use tower_cookies::CookieManagerLayer;
use tower_http::services::ServeDir;

#[tokio::main]
async fn main() -> std::io::Result<()> {
    fast_log::init(fast_log::Config::new().console()).expect("rbatis init err");
    let mut assets_dir = home_dir().unwrap();
    assets_dir.push(DATA_ROOT);
    assets_dir.push(STATIC_PATH);

    let router = Router::new()
        .route("/", get(template::index::index))
        .route("/index", get(template::index::index))
        .route("/post", get(template::post::index))
        .route("/post", post(topic_controller::save))
        .route("/post/upload", post(topic_controller::upload))
        .route("/search", get(template::search::index))
        .route("/rebuild", get(topic_controller::rebuild_index))
        .route("/setting", get(template::setting::index))
        .route("/setting", post(setting_controller::save))
        .route("/widget", get(template::widget::index))
        .route("/widget", post(widget_controller::save))
        .route("/widget/del", post(widget_controller::del))
        .route("/reply", get(template::reply::index))
        .route("/reply", post(reply_controller::save))
        .route("/reply/del", post(reply_controller::del))
        .route("/reply/audit", post(reply_controller::audit))
        .route("/reply/reply", post(reply_controller::reply))
        .route("/topic/del", post(topic_controller::del))
        .route("/topic/top", post(topic_controller::top))
        .route("/topic/pass", post(topic_controller::pass))
        .route("/topic/get", get(template::topic::index))
        .route("/class", get(template::class::index))
        .route("/class/save", post(class_controller::save))
        .route("/class/del", post(class_controller::del))
        .route("/login", get(template::login::index))
        .route("/login", post(login_controller::login))
        .route("/logout", get(login_controller::logout))
        .route("/sitemap", get(template::sitemap::index))
        .nest_service(STATIC_PREFIX, get_service(ServeDir::new(assets_dir)))
        // .layer(from_fn(handle_charset))
        .layer(from_fn(auth))
        .layer(CookieManagerLayer::new());

    //cron
    tokio::spawn(init_cron());

    tokio::spawn(topic_service::rebuild_index());

    let listener = tokio::net::TcpListener::bind(&AppContext::config().server_url)
        .await
        .unwrap();
    axum::serve(listener, router).await
}
